import assert from 'assert/strict'
import { calculateManualAdjustmentState, normalizeAssetAdjustmentInput } from '../utils/stakingAdjustment'

const now = new Date('2025-01-01T12:00:00Z')

interface TestCase {
  name: string
  fn: () => void
}

const testCases: TestCase[] = [
  {
    name: '본금 감소로 이미 발송 금액이 초과된 경우, 당일 분배를 즉시 종료한다',
    fn: () => {
      const state = calculateManualAdjustmentState({
        stakedAmount: 10,
        dailyRewardRate: 0.02,
        dailyRewardDistributed: 1.5,
        dailyDistributionCount: 6,
        nextDistributionAt: null,
        now
      })

      assert.equal(state.targetDailyReward, 0.2)
      assert.equal(state.effectiveDailyReward, 1.5)
      assert.equal(state.distributedToday, 1.5)
      assert.equal(state.remainingToday, 0)
      assert.equal(state.dailyDistributionCount, 12)
      assert.equal(state.scheduleClosedToday, true)
      assert.equal(state.cappedDueToReduction, true)
      assert.equal(state.nextDistributionAt, null)
    }
  },
  {
    name: '본금 증가 시 잔여 분배가 유지되고 다음 분배 시간이 재설정된다',
    fn: () => {
      const state = calculateManualAdjustmentState({
        stakedAmount: 150,
        dailyRewardRate: 0.02,
        dailyRewardDistributed: 1.0,
        dailyDistributionCount: 4,
        nextDistributionAt: null,
        now
      })

      assert.equal(state.targetDailyReward, 3)
      assert.equal(state.effectiveDailyReward, 3)
      assert.equal(state.distributedToday, 1)
      assert.equal(state.remainingToday, 2)
      assert.equal(state.dailyDistributionCount, 4)
      assert.equal(state.scheduleClosedToday, false)
      assert.equal(state.cappedDueToReduction, false)
      assert.ok(state.nextDistributionAt instanceof Date)
      assert.ok(state.nextDistributionAt!.getTime() > now.getTime())
    }
  },
  {
    name: '본금을 0으로 설정하면 당일 분배는 즉시 종료된다',
    fn: () => {
      const state = calculateManualAdjustmentState({
        stakedAmount: 0,
        dailyRewardRate: 0.02,
        dailyRewardDistributed: 0,
        dailyDistributionCount: 0,
        nextDistributionAt: null,
        now
      })

      assert.equal(state.targetDailyReward, 0)
      assert.equal(state.effectiveDailyReward, 0)
      assert.equal(state.distributedToday, 0)
      assert.equal(state.remainingToday, 0)
      assert.equal(state.dailyDistributionCount, 12)
      assert.equal(state.scheduleClosedToday, true)
      assert.equal(state.cappedDueToReduction, false)
      assert.equal(state.nextDistributionAt, null)
    }
  },
  {
    name: '금일 분배가 완료된 이후 수익률이 증가해도 분배 스케줄은 익일에 반영된다',
    fn: () => {
      const existingNext = new Date('2025-01-01T22:00:00Z')
      const state = calculateManualAdjustmentState({
        stakedAmount: 200,
        dailyRewardRate: 0.02,
        dailyRewardDistributed: 2,
        dailyDistributionCount: 12,
        nextDistributionAt: existingNext,
        now
      })

      assert.equal(state.targetDailyReward, 4)
      assert.equal(state.effectiveDailyReward, 4)
      assert.equal(state.distributedToday, 2)
      assert.equal(state.remainingToday, 2)
      assert.equal(state.dailyDistributionCount, 12)
      assert.equal(state.scheduleClosedToday, true)
      assert.equal(state.cappedDueToReduction, false)
      assert.equal(state.nextDistributionAt, null)
    }
  }
]

testCases.push({
  name: '자산 조정 입력은 음수를 0으로 보정하고 소수점 4자리까지 유지한다',
  fn: () => {
const normalized = normalizeAssetAdjustmentInput({
      stakedAmountNear: -50,
      lockedAmountNear: 5.67891,
      totalRewardsKrw: Number.NaN,
      availableRewardsKrw: -10.12345
})

    assert.equal(normalized.stakedAmountNear, 0)
    assert.equal(normalized.lockedAmountNear, 5.6789)
    assert.equal(normalized.totalRewardsKrw, 0)
    assert.equal(normalized.availableRewardsKrw, 0)
  }
})

let passed = 0

for (const testCase of testCases) {
  try {
    testCase.fn()
    console.log(`✅ ${testCase.name}`)
    passed += 1
  } catch (error) {
    console.error(`❌ ${testCase.name}`)
    console.error(error)
    process.exitCode = 1
    break
  }
}

if (passed === testCases.length) {
  console.log(`🎉 총 ${passed}개 테스트 통과`)
} else {
  console.error(`⚠️ 총 ${passed}/${testCases.length}개 테스트만 통과했습니다`)
  process.exit(1)
}
